﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Common;
using Common.Views;
using DataAccess;

namespace BL_WServices
{
    /// <summary>
    /// This is the WCF Service which is implementing the interface IUsersService
    /// </summary>
    public class UsersService : IUsersService
    {
        /// <summary>
        /// Returns the method AuthenticateUser from the UsersRepository whilst passing the parameters username, password and pin
        /// </summary>
        /// <param name="username">Of type string: Username of the user</param>
        /// <param name="token">Of type string: Password of the user</param>
        /// <param name="pin">Of type int: Pin of the user</param>
        /// <returns></returns>
        public bool AuthenticateUser(string username, string token, int pin)
        {
            return new UsersRepository().AuthenticateUser(username, token, pin);        
        }

        /// <summary>
        /// This method will allow the user to add his/her details into the database.
        /// It will check whether the username, email and pin exist, and if the username or email exists, an exception is thrown.
        /// Else it will input the user details into the database. The role of the registered user is set to Client
        /// </summary>
        /// <param name="username">Of type string: Username of the user</param>
        /// <param name="password">Of type string: Password of the user</param>
        /// <param name="name">Of type string: Name of the user</param>
        /// <param name="surname">Of type string: Surname of the user</param>
        /// <param name="email">Of type string: Email of the user</param>
        /// <param name="mobileNo">Of type string: MobileNo of the user</param>
        /// <param name="residence">Of type string: Residence of the user</param>
        /// <param name="street">Of type string: Street of the user</param>
        /// <param name="town">Of type string: Town of the user</param>
        /// <param name="country">Of type string: Country of the user</param>
        /// <param name="pinNo">Of type int: Pin No of the user</param>
        public void AddUser(string username, string password, string name, string surname, string email, 
            string mobileNo, string residence, string street, string town, string country, int pinNo)
        {
            UsersRepository ur = new UsersRepository(false);
            RolesRepository rr = new RolesRepository(false);
            ur.Entity = rr.Entity;
            
            User u = new User();
            u.Username = username;
            u.Password = password;
            u.Name = name;
            u.Surname = surname;
            u.Email = email;
            u.MobileNo = mobileNo;
            u.Residence = residence;
            u.Street = street;
            u.Town = town;
            u.Country = country;
            u.PinNumber = pinNo;

            try
            {
                ur.Entity.Connection.Open();
                rr.Transaction = ur.Transaction = ur.Entity.Connection.BeginTransaction();

                ur.AddUser(u);
                rr.AllocateRole(u, rr.GetRole(1));
                ur.Transaction.Commit();
            }
            catch
            {
                ur.Transaction.Rollback();
                throw new Exception("An error has occurred. Please try again later");
            }
            finally
            {
                ur.Entity.Connection.Close();
            }    
        }

        /// <summary>
        /// Checks whether the username actually exists. 
        /// </summary>
        /// <param name="username">Of type string. used to see whether this particular username exists. </param>
        /// <returns>Returns true or false</returns>
        public bool DoesUserNameExist(string username)
        {
            return new UsersRepository().DoesUserNameExist(username);
        }

        /// <summary>
        /// Checks whether the email actually exists. 
        /// </summary>
        /// <param name="email">Of type string. used to see whether this particular email exists. </param>
        /// <returns>Returns true or false</returns>
        public bool DoesEmailExist(string email)
        {
            return new UsersRepository().DoesEmailExist(email);
        }

        /// <summary>
        /// Checks whether the pinNo actually exists. 
        /// </summary>
        /// <param name="pinNo">Of type int. used to see whether this particular pinNo exists. </param>
        /// <returns>Returns true or false</returns>
        public bool DoesPinExist(int pinNo)
        {
            return new UsersRepository().DoesPinExist(pinNo);
        }

        /// <summary>
        /// Gets all the users.
        /// </summary>
        /// <returns>Returns Entity Users.</returns>
        public IQueryable<UsersView> GetUsernames()
        {
            return new UsersRepository().GetUsernames();
        }
    }
}
